{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Примерное содержание первого семестра:\n",
    "\n",
    "От исходного кода до исполняемого файла:\n",
    "* что есть программа на С++\n",
    "* процесс сборки \n",
    "* компилятор и некоторые его опции\n",
    "\n",
    "Фичи языка:\n",
    "* функции и операторы\n",
    "* классы\n",
    "* шаблоны\n",
    "* исключения\n",
    "* умные указатели\n",
    "* стандартные контейнеры и алгоритмы\n",
    "* лямбда-функции\n",
    "\n",
    "Практики разработки:\n",
    "* экосистема С++ проектов\n",
    "* практики производительности\n",
    "* юнит-тестирование: как и чем"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Лекция 1. Введение"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Обзор места языка на рынке\n",
    "\n",
    "* Зачем С++? Почему не язык X?\n",
    "    * Высокоуровневый язык с прямым отображением программы на железо\n",
    "        * нет прослойки типа виртуальной машины или интерпретатора\n",
    "        * C++ vs Python?\n",
    "        * С++ vs Java?\n",
    "    * Программист по умолчанию умный\n",
    "        * на момент создания языка - да\n",
    "        * в 2020-м - нет\n",
    "* Какова ниша С++?\n",
    "    * Примеры областей для использования:\n",
    "        * Игровые движки\n",
    "        * Физические движки\n",
    "        * Браузеры\n",
    "        * Компиляторы\n",
    "        * Backend\n",
    "        * ОС\n",
    "        * Математические пакеты\n",
    "        * HPC\n",
    "        * ...\n",
    "    * Что их объединяет?\n",
    "* Альтернативы на его нише?\n",
    "    * Rust\n",
    "        * создан на 30 лет позже С++\n",
    "        * учтён главный недостаток С++: программист по умолчанию больше не умный\n",
    "        * свободен от проблем обратной совместимости... пока что"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Замечание:** вопреки распространённому мнению, С++ уже не является \"надмножеством\" на языком С. Не каждая программа на языке С корректна для С++ (даже не учитывая простейших вещей типа новых ключевых слов). Стандарты С++ и С разошлись со временем. Неполный список расхождений [по стандарту](http://eel.is/c++draft/diff.iso), [по стандартной библиотеке](http://eel.is/c++draft/diff.library)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Запускаем Hello world"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hello world на С++ и что есть что.\n",
    "\n",
    "(что будет, если убрать каждый из элементов?)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "#include <cstdio>\n",
    "\n",
    "int main()\n",
    "{\n",
    "    std::puts(\"Hello world\");\n",
    "    return 0;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "От текста программы к исполняемому файлу. Зачем нужен компилятор."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#include <cstdio>\r\n",
      "\r\n",
      "int main()\r\n",
      "{\r\n",
      "    std::puts(\"Hello world\");\r\n",
      "    return 0;\r\n",
      "}\r\n",
      "\r\n"
     ]
    }
   ],
   "source": [
    "!cat hello_world.cpp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Шаг 1: компилятор преобразует файл программы на С++ в объектный файл - скомпилированный набор функций файла в виде инструкций ассемблера и констант"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -c -O3 hello_world.cpp -o hello_world.o"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Посмотрим на содержимое `hello_world.o`. Для этого воспользуемся утилитой `objdump`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r\n",
      "hello_world.o:     file format elf64-x86-64\r\n",
      "\r\n",
      "Contents of section .text:\r\n",
      " 0000 50bf0000 0000e800 00000031 c059c3    P..........1.Y. \r\n",
      "Contents of section .rodata.str1.1:\r\n",
      " 0000 48656c6c 6f20776f 726c6400           Hello world.    \r\n",
      "Contents of section .comment:\r\n",
      " 0000 00636c61 6e672076 65727369 6f6e2036  .clang version 6\r\n",
      " 0010 2e302e30 2d317562 756e7475 32202874  .0.0-1ubuntu2 (t\r\n",
      " 0020 6167732f 52454c45 4153455f 3630302f  ags/RELEASE_600/\r\n",
      " 0030 66696e61 6c2900                      final).         \r\n",
      "Contents of section .eh_frame:\r\n",
      " 0000 14000000 00000000 017a5200 01781001  .........zR..x..\r\n",
      " 0010 1b0c0708 90010000 14000000 1c000000  ................\r\n",
      " 0020 00000000 0f000000 00410e10 00000000  .........A......\r\n"
     ]
    }
   ],
   "source": [
    "!objdump -s hello_world.o"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Попросим `objdump` показать ассемблер секции с исполняемым кодом:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r\n",
      "hello_world.o:     file format elf64-x86-64\r\n",
      "\r\n",
      "\r\n",
      "Disassembly of section .text:\r\n",
      "\r\n",
      "0000000000000000 <main>:\r\n",
      "   0:\t50                   \tpush   %rax\r\n",
      "   1:\tbf 00 00 00 00       \tmov    $0x0,%edi\r\n",
      "   6:\te8 00 00 00 00       \tcallq  b <main+0xb>\r\n",
      "   b:\t31 c0                \txor    %eax,%eax\r\n",
      "   d:\t59                   \tpop    %rcx\r\n",
      "   e:\tc3                   \tretq   \r\n"
     ]
    }
   ],
   "source": [
    "!objdump -d hello_world.o"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Шаг 2: линковщик собирает несколько объектных файлов в один исполняемый"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "!clang++ -O3 hello_world.o -o hello_world.exe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Запустим:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world\r\n"
     ]
    }
   ],
   "source": [
    "!./hello_world.exe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Подчистим"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "!rm -f *.o *.exe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Итого:**\n",
    "\n",
    "```\n",
    "Исходный код\n",
    "    -- (компилятор) --> объектные файлы\n",
    "    -- (линковщик)  --> исполняемый файл\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Замечание:**\n",
    "\n",
    "Для маленьких программ можно пропустить промежуточный этап с объектными файлами, сразу сгенерировав исполяемый файл:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# нет опции \"-c\":\n",
    "!clang++ -O3 hello_world.cpp -o hello_world.exe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Вопрос:**\n",
    "\n",
    "Как переход от текста программы к её исполнению устроен в Java?  В Python?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Базовые типы данных"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "// https://en.cppreference.com/w/cpp/language/types\n",
    "\n",
    "int main()\n",
    "{\n",
    "    //\n",
    "    // boolean\n",
    "    //\n",
    "    bool b = true;\n",
    "    \n",
    "    //\n",
    "    // integer\n",
    "    //\n",
    "\n",
    "    // >= 16 byte\n",
    "    short s = 0;\n",
    "    unsigned short us = 0;\n",
    "        \n",
    "    // >= 16 byte\n",
    "    int x = 0;\n",
    "    unsigned int ux = 0;\n",
    "        \n",
    "    // >= 32 byte\n",
    "    long l = 0;\n",
    "    unsinged long ul = 0;\n",
    "\n",
    "    // >= 64 byte\n",
    "    long long ll = 0;\n",
    "    unsigned long long ull = 0;\n",
    "\n",
    "    std::int32_t i32 = 0;\n",
    "    std::int64_t i64 = 0;\n",
    "    std::uint32_t u32 = 0;\n",
    "    std::uint64_t u64 = 0;\n",
    "\n",
    "    //\n",
    "    // chars\n",
    "    //\n",
    "    char c = 0;\n",
    "    unsinged uc = 0;\n",
    "\n",
    "    std::char16_t c16 = 0;\n",
    "    std::char32_t c32 = 0;\n",
    "    \n",
    "    // 1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)\n",
    "    \n",
    "    //\n",
    "    // floats\n",
    "    //\n",
    "    float f = 0.f;        // usually 32-bit IEEE-754 type\n",
    "    double d = 0.;        // usually 64-bit IEEE-754 type\n",
    "    long double ld = 0.;  // usually 80-bit\n",
    "    \n",
    "    //\n",
    "    // pointers\n",
    "    //\n",
    "    int x = 3;\n",
    "    int y = 4;\n",
    "    int* p = nullptr;  // указатель на значение типа int\n",
    "    \n",
    "    p = &x;\n",
    "    *p = 5;  // теперь x == 5\n",
    "    p = &y;\n",
    "    *p = 6;  // теперь y == 6\n",
    "    p = nullptr;\n",
    "    *p = 7;  // ошибка\n",
    "\n",
    "    //\n",
    "    // c-style arrays:\n",
    "    //\n",
    "    int x[3] = {0, 1, 2};  // size must be known at compile time\n",
    "    x[2] = 5;\n",
    "    x[3] = 6;  // ooops\n",
    "    std::cout << \"x elements count = \" << std::size(x) << std::endl;\n",
    "\n",
    "    int y[] = {0, 1, 2};  // autodetect size at compile time\n",
    "    std::cout << \"y elements count = \" << std::size(y) << std::endl;\n",
    "\n",
    "    //\n",
    "    // c-style strings and pointers:\n",
    "    //\n",
    "    const char name[] = \"Petr\";  // array of symbols\n",
    "    std::cout << \"name length = \" << std::size(name) << std::endl;  // ?\n",
    "\n",
    "    const char *name2 = \"Petr\";  // pointer\n",
    "    // std::size(name2) вызвать нельзя, т.е. name2 - указатель\n",
    "    // вопрос: как узнать размер строки?\n",
    "\n",
    "    name2[0];  // P\n",
    "    name2[1];  // e\n",
    "    name2[2];  // t\n",
    "\n",
    "    *name2;        // P\n",
    "    *(name2 + 1);  // e\n",
    "    *(name2 + 2);  // t\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Пределы представления чисел:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "// https://en.cppreference.com/w/cpp/types/numeric_limits\n",
    "    \n",
    "#include <numeric_limits>\n",
    "    \n",
    "std::numeric_limits<std::int32_t>::max()\n",
    "std::numeric_limits<std::int64_t>::min()\n",
    "    \n",
    "std::numeric_limits<float>::max()\n",
    "std::numeric_limits<float>::min()\n",
    "std::numeric_limits<float>::lowest()\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###### Управляющие конструкции языка: `if-else`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Стандартная комбинация блоков `if-else`:\n",
    "\n",
    "```c++\n",
    "if (x % 2 == 0)\n",
    "{\n",
    "    std::puts(\"x is even\");\n",
    "}\n",
    "else\n",
    "{\n",
    "    std::puts(\"x is odd\");\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Блок `else` может быть опущен:\n",
    "\n",
    "```c++\n",
    "if (x % 2 == 0)\n",
    "{\n",
    "    std::puts(\"x is even\");\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "В случае блока из одной операции скобки для краткости можно опускать:\n",
    "    \n",
    "```c++\n",
    "if (x % 2 == 0)\n",
    "    std::puts(\"x is even\");\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Вычисления в условии:\n",
    "\n",
    "```c++\n",
    "if (int x = some_number())\n",
    "{\n",
    "    ... // do something with x != 0\n",
    "}\n",
    "\n",
    "if (int x = some_number(); x >= 5)\n",
    "{\n",
    "    ... // do something with x >= 5\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###### Управляющие конструкции языка: циклы"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "// for loop\n",
    "for (int i = 0; i < 100; ++i)\n",
    "{\n",
    "    ...\n",
    "}\n",
    "\n",
    "// range for\n",
    "std::vector v = {10, 20, 30, 40, 50};\n",
    "for (int i : v)\n",
    "{\n",
    "    ...\n",
    "}\n",
    "\n",
    "// while\n",
    "while (exression)\n",
    "{\n",
    "    ...\n",
    "}\n",
    "\n",
    "// do-while\n",
    "do\n",
    "{\n",
    "    ...\n",
    "}\n",
    "while (expression);\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Область видимости переменных"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Область видимости переменной ограничена блоком, в котором переменная определена.\n",
    "\n",
    "```c++\n",
    "{\n",
    "    ...;\n",
    "    int x = 5;\n",
    "    ...;\n",
    "}  // здесь заканчивается область видимости переменной x\n",
    "\n",
    "// здесь обращение к x невозможно\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример**:\n",
    "\n",
    "Предуперить студента, что он набрал слишком много курсов\n",
    "    \n",
    "```c++\n",
    "if (classes_count > 3)\n",
    "{\n",
    "    int excessive_count = classes_count - 3;\n",
    "    std::cout << \"too many classes, consider to leave: \"\n",
    "              << excessive_count\n",
    "              << std::endl;\n",
    "}\n",
    "// excessive_count после if недоступен, значение утеряно\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример** с переопределением:\n",
    "    \n",
    "```c++\n",
    "{\n",
    "    int x = 5;\n",
    "    \n",
    "    {\n",
    "        int x = 7;  // другая переменная с совпадающим именем\n",
    "                    // обратиться к прежнему x по имени нельзя\n",
    "        ...\n",
    "    }\n",
    "    \n",
    "    std::cout << x << std::endl;  // 5\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Стек и куча"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![img](stack_and_heap.png \"Стек и куча\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_(здесь нужно в zoom рисовать как отматывается стэк и что где лежит)_\n",
    "\n",
    "```c++\n",
    "void my_function()\n",
    "{\n",
    "    int x = 500;  // value on stack\n",
    "    int *p = &x;  // pointer to value (что такое указатель?)\n",
    "    \n",
    "    *p = 42;\n",
    "    std::cout << x;  // ??\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Размотка стека при вызове функции (упрощённый вариант):\n",
    "\n",
    "_(здесь нужно в zoom рисовать как отматывается стэк и что где лежит)_\n",
    "\n",
    "```c++\n",
    "void make_floor()\n",
    "{\n",
    "    float side = 3.f;\n",
    "    float height = 0.2f; /* ... */\n",
    "}\n",
    "\n",
    "void make_wall()\n",
    "{\n",
    "    float height = 3.f;\n",
    "    float width = 0.2f; /* ...; */\n",
    "}\n",
    "\n",
    "void build_house()\n",
    "{\n",
    "    int price = 100500;\n",
    "    make_floor();\n",
    "    make_wall();\n",
    "    make_wall();\n",
    "    std::cout << \"your bill: \" << price << std::endl;\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "    build_house();\n",
    "    return 0;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Куча (heap):"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_(здесь нужно в zoom рисовать как отматывается стэк и что где лежит)_\n",
    "\n",
    "```c++\n",
    "void my_function()\n",
    "{\n",
    "    int *p = (int *)malloc(sizeof(int));  // pointer to value on heap\n",
    "    *p = 500;\n",
    "    int x = *p;                    // value on stack\n",
    "\n",
    "    *p = 42;\n",
    "    std::cout << x;  // ??\n",
    "    \n",
    "    free(p);\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Задача**: найдите ошибку\n",
    "\n",
    "```c++\n",
    "// функция возвращает указатель на ячейку памяти,\n",
    "// где лежит цена дома\n",
    "int* get_house_price()\n",
    "{\n",
    "    int price = 100500;\n",
    "    return &price;\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "    int *p = get_house_price();\n",
    "    std::cout << \"your bill: \" << *p << std::endl;\n",
    "    return 0;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### C / C++  строки"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "//\n",
    "// С-строки\n",
    "//\n",
    "// функции стандартной библиотеки для работы со строками в стиле С\n",
    "// https://en.cppreference.com/w/cpp/string/byte\n",
    "\n",
    "const char* cname = \"cpushkin\";  // where? len?\n",
    "std::cout << cname << std::endl;\n",
    "\n",
    "char* pcname = (char*)malloc(sizeof(char) * (strlen(cname) + 1));  // where? +1?\n",
    "strcpy(pcname, cname);\n",
    "std::cout << pcname << std::endl;\n",
    "free(pcname);\n",
    "\n",
    "const char* greeting = \"Ai da \" + cname; // ! ERROR\n",
    "\n",
    "char s[100];\n",
    "sprintf(s, \"%i\", 42);\n",
    "\n",
    "\n",
    "//\n",
    "// C++ - строки\n",
    "//\n",
    "// класс стандартной строки:\n",
    "// https://en.cppreference.com/w/cpp/string/basic_string\n",
    "//\n",
    "// функции конвертации строк:\n",
    "// https://en.cppreference.com/w/cpp/string/basic_string/to_string\n",
    "\n",
    "std::string cppname = \"cpppushkin\";\n",
    "std::cout << cppname << std::endl;\n",
    "                \n",
    "std::string prep = \"Ai da\";\n",
    "std::string greeting = prep + \" \" + cppname; // OK\n",
    "        \n",
    "std::string s = std::to_string(42);\n",
    "\n",
    "std::string* pcppname = &cppname; // what is it?\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Функции"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Напишем функцию, вычисляющую длину двумерного вектора:\n",
    "\n",
    "Подробно рассказать что есть что в этом коде."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "float length(float x, float y)\n",
    "{\n",
    "    float sqrLength = x * x + y * y;\n",
    "    return std::sqrt(sqrLength);\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Вызов функции:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "float len = length(3.f, 4.f);\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Если функция не должна ничего возвращать, есть специально зарезервированное слово `void`:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void log_person_arrived_to_airport(const char* name)\n",
    "{\n",
    "    ...\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Передача аргументов в функцию"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "По значению:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void f(int n)\n",
    "{\n",
    "    ++n;\n",
    "    std::clog << n << std::endl;\n",
    "}\n",
    "\n",
    "\n",
    "x = 3;\n",
    "f(x);  // 4\n",
    "std::cout << x << std::endl;  // 3\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "По ссылке:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void f(int& n)\n",
    "{\n",
    "    ++n;\n",
    "    std::clog << n << std::endl;\n",
    "}\n",
    "\n",
    "\n",
    "x = 3;\n",
    "f(x);  // 4\n",
    "std::cout << x << std::endl;  // 4\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Вариант - по константной ссылке:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void f(const int& n)\n",
    "{\n",
    "    ++n;  // COMPILER ERROR!\n",
    "    std::clog << n << std::endl;\n",
    "}\n",
    "\n",
    "\n",
    "x = 3;\n",
    "f(x);\n",
    "std::cout << x << std::endl;\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "В каком случае лучше передвать по значению, а когда по ссылке?\n",
    "* дешёвые для копирования объекты - по значению\n",
    "* дорогие для копирования объекты - по ссылке"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Рассмотрим разницу:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "std::string get_full_name(const std::string& name, const std::string& surname)\n",
    "{\n",
    "    return name + \" \" + surname;\n",
    "}\n",
    "\n",
    "std::string get_full_name(std::string name, std::string surname)\n",
    "{\n",
    "    return name + \" \" + surname;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "А если так, в чём проблема?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "std::string get_full_name(std::string& name, std::string& surname)\n",
    "{\n",
    "    return name + \" \" + surname;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "А что происходит здесь?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "std::string get_full_name(std::string *name, std::string *surname)\n",
    "{\n",
    "    return *name + \" \" + *surname;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<br />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Замечания после лекции**:\n",
    "1. Материал про objdump и содержимое объектных файлов не идёт. Во-первых, плохо понятно, зачем оно надо, особенно на этом этапе знакомства. Во-вторых, тяжеловато для старта. Нужно сократить. В крайнем случае показывать уже содержимое исполняемого файла, а лучше совсем не показывать. (всё равно семинар не успели почти полностью)\n",
    "2. Рассказ про строки С / С++ не впечатляет. Слишком много кода и контекста. Нужно ярче и короче выделить идею, сравнение и примеры. Возможно, параллельно сравнивать решения, обсуждая их детали.\n",
    "3. Добавить пример на добавление константы к указателю, что число прибавляется умноженным на размер типа в байтах.\n",
    "4. Дорассказать от семинара на следующем занятии: агрументы командной строки, `.h` vs `.cpp`"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
